function varargout = st_trans(d, type, varargin)
% function varargout = st_trans(d, type, varargin)
%
% Wrapper function for performing several types of short-time transforms:
%   'spec' - Short Time Fourier Transform (uses Signal Processing Toolbox's
%            'specgram function)
%   'desp' - Dan Ellis' replacement for specgram
%   'stft' - Short Time Fourier Transform (uses Dan Ellis' stft.m)
%   'logf' - Constant-Q transform based on Dan Ellis' code.
%
% Input:
%   d        [vec]  - Mono vector of data to transform
%   type     [str]  - Type of transform to do ('spec', 'desp', 'stft', or 
%                     'logf') ['spec']
% (OPTIONAL):
%   dsr      [num]  - Desired sampling rate [8000]
%   nfft     [num]  - FFT size to use for each frame [512]
%   win      [num]  - Length (in seconds) of each window [0.064]
%   hop      [num]  - Length (in seconds) of the overlap of each frame [0.016]
%   bpo      [num]  - Bands per octave (only needed for Constant-Q) [12]
%   mag_only [bool] - Magnitude only? [true]
%   min_freq [num]  - Minimum frequency (in Hz) to display
%   db_range [vec]  - dB range to display (only used with imagesc) [-80 20]
%
% Output:
%   dat      [mat]  - The spectrogram.  If no output argument is specified,
%                     then the spectrogram is plotted instead using Ron
%                     Weiss' 'plotall' function (if it exists on the path)
%                     or imagesc.
%

% Copyright (C) 2010-2030 Graham Grindlay (grindlay@ee.columbia.edu)
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

[dsr, nfft, win, hop, bpo, mag_only, minf, db_range] = ...
    parse_opt(varargin, 'dsr', 8000, 'nfft', 512, 'win', 0.064, ...
                        'hop', 0.016, 'bpo', 12, 'mag_only', 1, ...
                        'min_freq', 10, 'db_range', [-80 20]);
                    
if nargin < 2
    type = 'spec';
end

switch type
    case 'spec' % Mathworks spectrogram
        dat = spectrogram(d, ceil(win*dsr), ceil(win*dsr)-ceil(hop*dsr), nfft);
        
    case 'desp' % Dan Ellis' myspecgram function
        dat = myspecgram(d, nfft, dsr, ceil(win*dsr), ceil(win*dsr)-ceil(hop*dsr));
        
    case 'stft' % Dan Ellis' stft function
        dat = stft(d, nfft, ceil(win*dsr), ceil(hop*dsr));
        
    case 'logf' % Dan Ellis' logfsgram function
        dat = logfsgram(d, nfft, dsr, ceil(win*dsr), ceil(win*dsr)-ceil(hop*dsr), minf, bpo);
        
    otherwise
        error('Bad transform type given.');
end

if mag_only
    dat = abs(dat);
end

% display spectrogram if no output arguments given
if nargout == 0
    % check for Ron Weiss' plotall function
    if exist('plotall', 'file')==2
        plotall(dB(abs(dat)), 'xlabel', 'Time (sec)', 'ylabel', 'Frequency (Hz)', 'xticklabel', @() get(gca, 'xtick')*hop);
    else % use builtin
        imagesc([0 length(d)/dsr], [1 size(dat,1)], 20*log10(abs(dat)), db_range);
        axis xy
        xlabel('Time (sec)');
        ylabel('Frequency (Hz)');
        colorbar;
    end
    
    yt = get(gca,'YTick');
    nfrq = length(yt);
    ytl = cell(1,nfrq);
    
    if strcmp(type, 'logf')
        fratio = 2^(1/bpo);
        
        % How many bins in log-f axis
        nbins = floor( log((dsr/2)/minf) / log(fratio) );
        
        % Freqs corresponding to each bin in log F output
        logffrqs = minf * exp(log(2)*(0:(nbins-1))/bpo);
        fqs = logffrqs(yt);
    else
        fqs=(dsr/(nfrq*2)):(dsr/(nfrq*2)):(dsr/2);
    end
    
    for i = 1:nfrq
        ytl{i} = sprintf('%.0f',fqs(i));
    end
    set(gca,'YTickLabel',ytl);
else
    varargout{1} = dat;
end

